package com.ztstkj.lzservices.serialports

import com.jackiepenghe.serialportlibrary.MultipleSerialPortManager
import com.ztstkj.lzservices.events.EventCard
import com.ztstkj.lzservices.events.EventCategory
import com.ztstkj.lzservices.events.EventRate
import com.ztstkj.lzservices.events.EventWeight
import com.ztstkj.lzservices.extension.ByteArrayExtension.toHexStr
import com.ztstkj.lzservices.extension.ExceptionExt.toStackTraceString
import com.ztstkj.lzservices.mmkvs.MmkvManager
import com.ztstkj.lzservices.utils.ScaleStabilityChecker
import org.greenrobot.eventbus.EventBus

object SerialPortUtil {
    private const val TTYS3 = "/dev/ttyS3"
    private const val TTYS3BAUDRATE = 9200
    private const val TTYS4 = "/dev/ttyS4"
    private const val TTYS4BAUDRATE = 19200


    fun openS3(dataCallback: onReciverListener? = null) {
        open(TTYS3, TTYS3BAUDRATE, dataCallback)
    }


    fun openS4(dataCallback: onReciverListener? = null) {
        open(TTYS4, TTYS4BAUDRATE, dataCallback)
    }

    val stabilityChecker = ScaleStabilityChecker(windowSize = 5, threshold = 0.2f)


    private fun open(path: String, baudrate: Int, dataCallback: onReciverListener?) {
        if (!MultipleSerialPortManager.isOpened(path)) {
            var result = MultipleSerialPortManager.openSerialPort(path, baudrate) { data, size ->
                try {
                    val modbusData = ModbusData(data)
                    if (modbusData.slaveId != 1) return@openSerialPort
                    if (!modbusData.crc16Verify()) {
                        MmkvManager.addLog("${path}收到：", data.toHexStr(" ") + "($size)")
                        write(path, modbusData.error(ModbusError.CRC_ERROR))
                        return@openSerialPort
                    }
                    if(modbusData.operate!=ModbusOperate.Weight)
                        MmkvManager.addLog("${path}收到：", data.toHexStr(" ") + "($size)$modbusData")
                    //val gson = Gson().toJson(data)
                    //MmkvManager.addLog("解析报文", gson)
                    when (modbusData.operate) {
                        ModbusOperate.Card -> {
                            EventBus.getDefault().post(EventCard(modbusData.carNo, modbusData))
                        }
                        ModbusOperate.Weight -> {
                            write(path, modbusData.success(),false)
                            EventBus.getDefault().post(EventWeight(true,modbusData.weight))
                            /*
                            val (isStable, stableValue) = stabilityChecker.checkStability(modbusData.weight.toFloat())
                            write(path, modbusData.success(),false)
                            if (isStable && stableValue != null) {
                                EventBus.getDefault().post(EventWeight(true, stableValue.toInt()))
                            } else {
                                EventBus.getDefault().post(EventWeight(false, modbusData.weight))
                            }
                             */
                        }
                        ModbusOperate.Category -> {
                            write(path, modbusData.success())
                            EventBus.getDefault().post(EventCategory(modbusData.category))
                        }
                        ModbusOperate.Rate -> {
                            write(path, modbusData.success())
                            EventBus.getDefault().post(
                                EventRate(modbusData.carNo, modbusData.category, modbusData.rate, modbusData.weight)
                            )
                        }

                        ModbusOperate.Time -> {
                            write(path, modbusData.successTime())
                        }

                        null -> {}
                        //dataCallback?.onRecived(data)
                        //
                    }
                } catch (e: Exception) {
                    MmkvManager.addLog("解析报文异常", e.toStackTraceString())
                }
            }
            MmkvManager.addLog("串口开启", "${path}:${result}")
        }
    }

    fun writeS3(data: ByteArray) {
        write(TTYS3, data)
    }

    fun writeS4(data: ByteArray) {
        write(TTYS4, data)
    }

    private fun write(path: String, data: ByteArray, isLog: Boolean = true) {
        MultipleSerialPortManager.writeData(path, data)
        if (isLog)
            MmkvManager.addLog(path + "发送：", data.toHexStr(" ")) //记录日志
    }

    fun close() {
        MultipleSerialPortManager.closeAll()
    }

    interface onReciverListener {
        fun onRecived(data: ByteArray)
    }
}